﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DAL.Helpers;
using Model.Entities;
using Model.RepositoryInterfaces;
using Model.ViewModels;

namespace DAL.Repositories
{
    public class SearchRepository:ISearchRepository
    {
        private string _stringQuery = "from Apartment";
        private bool _optionalParam = false;
        private bool _needsAnd = false;

        #region Implementation of ISearchRepository

        public ApartmentDetailsVm GetApartmentDetails(int apartmentId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                var apartment = session.Get<Apartment>(apartmentId);

                if (apartment != null)
                {
                    var detailsViewModel = new ApartmentDetailsVm()
                    {
                        Id = apartment.Id,
                        Code = apartment.Code,
                        Building = apartment.Building,
                        State = EnumHelper.GetEnumName(typeof(ApartmentState), apartment.State), 
                        Floor = EnumHelper.GetEnumName(typeof(Floor), apartment.Floor),
                        RoomsNumber = EnumHelper.GetEnumName(typeof(NumOfRooms), apartment.NumOfRooms),
                        Facade = EnumHelper.GetEnumName(typeof(ApartmentFacade), apartment.Facade),
                        Price = Math.Round(apartment.Price, 2),
                        Area = Math.Round(apartment.Area, 2)
                    };

                    return detailsViewModel;
                }
                else
                {
                    return new ApartmentDetailsVm();
                }
            }
        }

        public IList<ApartmentSearchVm> Search(string floorId, string areaValueIntervalId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                if (floorId != "sve")
                {
                    CheckWhere();
                    CheckAnd();
                    _stringQuery += "Floor = :floorId";
                }
                if (areaValueIntervalId != "sve")
                {
                    CheckWhere();
                    CheckAnd();
                    _stringQuery += "Area between :lowerArea and :upperArea";
                }
                
                //dohvati samo neprodane stanove 
                CheckWhere();
                CheckAnd();
                _stringQuery += "State <> :stateId";

                var query = session.CreateQuery(_stringQuery);
                
                if (floorId != "sve")
                {
                    query.SetParameter("floorId", floorId);
                }
                if (areaValueIntervalId != "sve")
                {
                    var intervalRep = new IntervalRepository();
                    var areaValueInterval = intervalRep.Read(Convert.ToInt32(areaValueIntervalId));
                    query.SetParameter("lowerArea", areaValueInterval.LowerBoundary).SetParameter("upperArea", areaValueInterval.UpperBoundary);
                }
                query.SetParameter("stateId", ApartmentState.Prodano);

                var apartments = query.List<Apartment>();

                return (from apartment in apartments
                        select new ApartmentSearchVm()
                        {
                            Id = apartment.Id, 
                            Code = apartment.Code, 
                            Floor = EnumHelper.GetEnumName(typeof (Floor), apartment.Floor), 
                            NumOfRooms = EnumHelper.GetEnumName(typeof (NumOfRooms), apartment.NumOfRooms), 
                            Area = Math.Round(apartment.Area, 2),
                            Price = Math.Round(apartment.Price, 2)
                        }).ToList();
            }
        }

        public IList<ApartmentSearchVm> SearchByKeyword(string keyword)
        {
            var vmList = new List<ApartmentSearchVm>();

            using (var session = NHibernateHelper.OpenSession())
            {
                var sql = String.Format("SELECT Apartment_id FROM {0} WHERE DIFFERENCE(Code, {1}) = 4 OR DIFFERENCE(Floor, {1}) >= 3 OR DIFFERENCE(NumOfRooms, {1}) >= 3 OR DIFFERENCE(Facade, {1}) >= 3", "ApartmentSearch", "'" + keyword + "'");
                var query = session.CreateSQLQuery(sql);
                var identificators = query.List<int>();

                vmList.AddRange(from identificator in identificators
                                select session.Get<Apartment>(identificator)
                                into apartment where apartment.State != ApartmentState.Prodano  
                                select new ApartmentSearchVm()
                                {
                                    Id = apartment.Id, 
                                    Code = apartment.Code, 
                                    Floor = EnumHelper.GetEnumName(typeof (Floor), apartment.Floor), 
                                    NumOfRooms = EnumHelper.GetEnumName(typeof (NumOfRooms), apartment.NumOfRooms), 
                                    Area = Math.Round(apartment.Area, 2),
                                    Price = Math.Round(apartment.Price, 2)
                                });
            }
            return vmList;
        }

        public IList<ApartmentByFloorVm> GetInfoByFloor(string floorId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                if (floorId != "sve")
                {
                    _stringQuery += " where Floor = :floorId";
                }
                var query = session.CreateQuery(_stringQuery);

                if (floorId != "sve")
                {
                    query.SetParameter("floorId", floorId);
                }
                var apartments = query.List<Apartment>();

                return apartments.Select(
                    apartment => new ApartmentByFloorVm()
                    {
                        Id = apartment.Id, 
                        Code = apartment.Code, 
                        Model = apartment.Model, 
                        State = EnumHelper.GetEnumName(typeof (ApartmentState), apartment.State), 
                        Price = Math.Round(apartment.Price, 2)
                    }).ToList();
            }
        }

        #endregion

        public void CheckWhere()
        {
            if (_optionalParam == false)
            {
                _optionalParam = true;
                _stringQuery += " where ";
            }
        }

        public void CheckAnd()
        {
            if (_needsAnd == false)
            {
                _needsAnd = true;
            }
            else
            {
                _stringQuery += " and ";
            }
        }
    }
}
